package openjdk.concurrent;

import java.util.Date;
import java.util.concurrent.CyclicBarrier;

/**
 * CyclicBarrier提供的关键方法如下
 * <p>
 * await() 等待其它参与方的到来（调用await()）。
 * 如果当前调用是最后一个调用，则唤醒所有其它的线程的等待并且如果在构造CyclicBarrier时指定了action，
 * 当前线程会去执行该action，然后该方法返回该线程调用await的次序（getParties()
 * -1说明该线程是第一个调用await的，0说明该线程是最后一个执行await的），接着该线程继续执行await后的代码；
 * 如果该调用不是最后一个调用，则阻塞等待；
 * 如果等待过程中，当前线程被中断，则抛出InterruptedException；
 * 如果等待过程中，其它等待的线程被中断，或者其它线程等待超时，或者该barrier被reset，或者当前线程在执行barrier构造时注册的action时
 * 因为抛出异常而失败，则抛出BrokenBarrierException。
 * await(long timeout, TimeUnit unit) 与await()唯一的不同点在于设置了等待超时时间，等待超时时会抛出TimeoutException。
 * reset() 该方法会将该barrier重置为它的初始状态，并使得所有对该barrier的await调用抛出BrokenBarrierException。
 * <p>
 * 从执行结果可以看到，每个线程都不会在其它所有线程执行await()方法前继续执行，
 * 而等所有线程都执行await()方法后所有线程的等待都被唤醒从而继续执行。
 */
public class CyclicBarrierDemo2 {

    public static void main(String[] args) {
        int totalThread = 5;
        CyclicBarrier barrier = new CyclicBarrier(totalThread);

        for (int i = 0; i < totalThread; i++) {
            String threadName = "Thread " + i;
            new Thread(() -> {
                System.out.println(String.format("%s\t%s %s", new Date(), threadName, " is waiting"));
                try {
                    barrier.await();
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
                System.out.println(String.format("%s\t%s %s", new Date(), threadName, "ended"));
            }).start();
        }
        System.out.println(">>>> Game over!");
    }
}
